home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / demo / rotplnnr.lha / RoutePlanner.c < prev    next >
C/C++ Source or Header  |  1994-08-22  |  68KB  |  2,317 lines

  1. /* RoutePlanner.c -- A fancy-ass front-end for RoadRoute */
  2. /* (C) 1994 Chris Lawrence */
  3.  
  4. #include "RoutePlanner.h"
  5. #include "RoutePlanner_rev.h"
  6.  
  7. #include <proto/dos.h>
  8. #include <proto/exec.h>
  9. #include <proto/muimaster.h>
  10. #include <proto/icon.h>
  11. #include <proto/utility.h>
  12. #include <proto/intuition.h>
  13. #include <proto/asl.h>
  14.  
  15. #include <libraries/mui.h>
  16. #include <libraries/gadtools.h>
  17.  
  18. #include <dos.h>
  19.  
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23.  
  24. #include <reg.h>
  25.  
  26. extern struct Library *MUIMasterBase;
  27. extern struct Library *IconBase;
  28. extern struct Library *UtilityBase;
  29. extern struct IntuitionBase *IntuitionBase;
  30. extern struct Library *AslBase;
  31.  
  32. void _STD_32767_killapp(void);
  33. void main(int argc, char **argv);
  34. ULONG ChooseCity(struct CityData *cd, ULONG Cities, ULONG CurrentCity,
  35.   char *tbar);
  36. BOOL OpenDatabase(char *filename, struct CityData **cd,
  37.   struct RouteData **rd);
  38. BOOL GetFile(char *filename, BOOL saverequest, char *tbar);
  39. void AddListEntries(APTR list, struct CityData *cd, ULONG CityCount);
  40. void Navigate(struct CityData *cd, struct CityData *Start,
  41.   struct CityData *Finish);
  42. BOOL NavCoord(struct CityData *cd, struct RouteData *rd,
  43.   ULONG fromID, ULONG toID, ULONG *viaID, ULONG viacount);
  44. UWORD ConvertDist(UWORD srcDist, UWORD srcUnits, UWORD destUnits);
  45. UWORD ConvertToTime(UWORD Code, UWORD SVal, UWORD Dist, UWORD RteUnits,
  46.   UWORD SysUnits);
  47. UWORD ConvertEfficiency(UWORD srcEff, UWORD SrcUnits, UWORD destUnits);
  48.  
  49. void SPrintf(char *outstr, char *fmt, ...);
  50.  
  51. #define ROUTETYPES    18
  52.  
  53. // Special list constructors and destructors
  54. APTR __saveds __asm constructor(register __a2 APTR pool,
  55.   register __a1 struct CityData *entry);
  56.  
  57. APTR __saveds __asm constructor(register __a2 APTR pool,
  58.   register __a1 struct CityData *entry)
  59. {
  60.   struct CityName *cn;
  61.   
  62.   if(cn=malloc(sizeof(struct CityName)))
  63.     {
  64.     cn->cn_CityID=entry->CityID;
  65.     SPrintf(cn->cn_Name,"%s, %s",entry->CityName,entry->StateName);
  66.     }
  67.   
  68.   return cn;
  69. }
  70.  
  71. VOID __saveds __asm destructor(register __a2 APTR pool,
  72.   register __a1 struct CityName *entry);
  73.  
  74. VOID __saveds __asm destructor(register __a2 APTR pool,
  75.   register __a1 struct CityName *entry)
  76. {
  77.   free(entry);
  78. }
  79.  
  80. LONG __saveds __asm display(register __a2 char **array,
  81.   register __a1 struct CityName *cn);
  82.  
  83. LONG __saveds __asm display(register __a2 char **array,
  84.   register __a1 struct CityName *cn)
  85. {
  86.   *array=cn->cn_Name;
  87.   
  88.   return 0;
  89. }
  90.  
  91. LONG __saveds __asm compare(register __a1 struct CityName *cn1,
  92.   register __a2 struct CityName *cn2);
  93.  
  94. LONG __saveds __asm compare(register __a1 struct CityName *cn1,
  95.   register __a2 struct CityName *cn2)
  96. {
  97.   return(Stricmp(cn1->cn_Name,cn2->cn_Name));
  98. }
  99.  
  100. struct Hook comphook={{NULL,NULL},&compare,NULL,NULL};
  101. struct Hook consthook={{NULL,NULL},(HOOKFUNC)&constructor,NULL,NULL};
  102. struct Hook desthook={{NULL,NULL},(HOOKFUNC)&destructor,NULL,NULL};
  103. struct Hook disphook={{NULL,NULL},&display,NULL,NULL};
  104.   
  105. // General Defines
  106. #define MAXTRAIL  1000 // Visit up to 1000 cities on a route
  107. #define COPYRIGHT VERS" ("DATE") -- Copyright 1994 Chris Lawrence"
  108. #define MAXVIA    10
  109.  
  110. static struct CityTrail Trail[MAXTRAIL][2];
  111. unsigned short TrailPoint[2];
  112.  
  113. // Global variables
  114. APTR app=NULL, mainwindow=NULL, POP_DBase=NULL;
  115. APTR prefswindow,CY_Measure,ST_Speed[ROUTETYPES],ST_MPG[ROUTETYPES];
  116. APTR LB_Speed[ROUTETYPES], LB_MPG[ROUTETYPES];
  117. APTR ST_DBase, BT_DBase, ST_DefaultMPG, LB_DefaultMPG;
  118.  
  119. APTR LI_ViaList, LV_ViaList;
  120. APTR TX_FromCity, TX_ToCity, BT_FromCity, BT_ToCity;
  121. APTR BT_DoRoute, BT_Quit, BT_SavePrefs, BT_UsePrefs, BT_CancelPrefs;
  122. APTR GP_Speed[2], GP_MPG[2], REG_Prefs;
  123. APTR BT_AddCity, BT_ChangeCity, BT_RemoveCity, BT_MoveUp, BT_MoveDown;
  124.  
  125. ULONG MeasureUnits, Speed[ROUTETYPES], MPG[ROUTETYPES], DefaultMPG;
  126. ULONG DisplayType, debugoutput;
  127.  
  128. #define DIS_ALL         (0L)
  129. #define DIS_ROUTECHANGE (1L)
  130. #define DIS_STATECHANGE (2L)
  131.  
  132. struct DiskObject *disko=NULL;
  133.  
  134. APTR memptr=NULL;
  135.  
  136. ULONG cdcount, rdcount;
  137.  
  138. struct DataBaseInfo *dbi=NULL;
  139.  
  140. APTR DLabel(const char *string);
  141.  
  142. APTR DLabel(const char *string)
  143. {
  144.   APTR tmp;
  145.   
  146.   tmp=TextObject,
  147.         StringFrame,
  148.         MUIA_FramePhantomHoriz, TRUE,
  149.         MUIA_Text_SetMin,   FALSE,
  150.         MUIA_Text_SetMax,   FALSE,
  151.         MUIA_FixWidthTxt,   "km/h",
  152.         MUIA_Text_PreParse, MUIX_L,
  153.         MUIA_Text_Contents, string,
  154.         MUIA_InputMode,     MUIV_InputMode_None,
  155.         End;
  156.   
  157.   return tmp;
  158. }
  159.  
  160. void _STD_32767_killapp(void)
  161. {
  162.   // SAS/C Autotermination function
  163.   
  164.   // This removes the application using MUI_DisposeObject. It is called
  165.   // when the program exits. Normal exits would also save the application
  166.   // object.
  167.   
  168.   if(memptr) free(memptr);
  169.   
  170.   if(disko) FreeDiskObject(disko);
  171.   if(app) MUI_DisposeObject(app);
  172. }
  173.  
  174. // Defines for menus and gadgets
  175. #define ABOUT        (1L)
  176. #define QUIT        (MUIV_Application_ReturnID_Quit)
  177. #define OPEN        (2L)
  178. #define PREFS        (3L)
  179. #define HIDE        (4L)
  180. #define USEPREFS    (5L)  // Store to ENV:
  181. #define SAVEPREFS    (6L)  // Store to ENV: and ENVARC:
  182. #define CANCELPREFS    (7L)  // Same as RestorePrefs
  183. #define OPENPREFS    (8L)
  184. #define SAVEPREFSAS    (9L)
  185. #define RESTOREPREFS    (10L)  // Restore from ENV:
  186. #define RESETPREFS    (11L) // Reset to defaults
  187. #define LASTSAVEDPREFS    (12L) // Restore from ENVARC:
  188.  
  189. #define FROMCITY    (13L)
  190. #define TOCITY        (14L)
  191. #define DOROUTE        (15L)
  192.  
  193. #define ADDCITY         (17L)
  194. #define CHANGECITY      (18L)
  195. #define REMOVECITY      (19L)
  196. #define MOVEUP          (20L)
  197. #define MOVEDOWN        (21L)
  198. #define VIALIST        (22L)
  199.  
  200. #define MEASURECHANGE   (23L)
  201.  
  202. #define INFO        (24L)
  203.  
  204. // Main window menu set
  205. struct NewMenu mainmenu[]={
  206.   NM_TITLE,"Project",NULL,0L,0L,NULL,
  207.    NM_ITEM,"Open Map...","O",0L,0L,(APTR)OPEN,
  208.    NM_ITEM,NM_BARLABEL,NULL,0L,0L,NULL,
  209.    NM_ITEM,"About...","?",0L,0L,(APTR)ABOUT,
  210.    NM_ITEM,"Information...","I",0L,0L,(APTR)INFO,
  211.    NM_ITEM,NM_BARLABEL,NULL,0L,0L,NULL,
  212.    NM_ITEM,"Hide","H",0L,0L,(APTR)HIDE,
  213.    NM_ITEM,"Quit","Q",0L,0L,(APTR)QUIT,
  214.   NM_TITLE,"Settings",NULL,0L,0L,NULL,
  215.    NM_ITEM,"Preferences...","P",0L,0L,(APTR)PREFS,
  216.   NM_END,NULL,NULL,0L,0L,NULL
  217.   };
  218.  
  219. // Prefs window menu set
  220. struct NewMenu prefsmenu[]={
  221.   NM_TITLE,"Prefs",NULL,0L,0L,NULL,
  222.    NM_ITEM,"Open...","O",0L,0L,(APTR)OPENPREFS,
  223.    NM_ITEM,"Save As...","A",0L,0L,(APTR)SAVEPREFSAS,
  224.    NM_ITEM,NM_BARLABEL,NULL,0L,0L,NULL,
  225.    NM_ITEM,"Close Prefs","C",0L,0L,(APTR)CANCELPREFS,
  226.    NM_ITEM,"Quit RoutePlanner","Q",0L,0L,(APTR)QUIT,
  227.   NM_TITLE,"Edit",NULL,0L,0L,NULL,
  228.    NM_ITEM,"Reset to Defaults","D",0L,0L,(APTR)RESETPREFS,
  229.    NM_ITEM,"Last Saved","L",0L,0L,(APTR)LASTSAVEDPREFS,
  230.    NM_ITEM,"Restore","R",0L,0L,(APTR)RESTOREPREFS,
  231.   NM_TITLE,"Settings",NULL,NM_MENUDISABLED,0L,NULL,
  232.    NM_ITEM,"Create Icons?","I",CHECKIT|MENUTOGGLE,0L,NULL,
  233.   NM_END,NULL,NULL,0L,0L,NULL
  234.   };
  235.  
  236. __inline APTR MakeMenustrip(struct NewMenu *nm);
  237.  
  238. __inline APTR MakeMenustrip(struct NewMenu *nm)
  239. {
  240.   return MUI_MakeObject(MUIO_MenustripNM,nm,0);
  241. }
  242.  
  243. APTR KeyPopButton(ULONG img, char key);
  244.  
  245. APTR KeyPopButton(ULONG img, char key)
  246. {
  247.   return (ImageObject,
  248.            ImageButtonFrame,
  249.            MUIA_ControlChar, key,
  250.            MUIA_Image_Spec, img,
  251.            MUIA_Image_FontMatch, TRUE,
  252.            MUIA_InputMode, MUIV_InputMode_RelVerify,
  253.            MUIA_Background, MUII_ButtonBack,
  254.            End);
  255. }
  256.  
  257. #define setinteger(obj,num) set(obj,MUIA_String_Integer,num)
  258.  
  259. #undef KeyButton
  260. APTR KeyButton(char *label, char key);
  261.  
  262. APTR KeyButton(char *label, char key)
  263. {
  264.   return (TextObject,
  265.            ButtonFrame,
  266.            MUIA_Text_Contents, label,
  267.            MUIA_Text_PreParse, MUIX_C,
  268.            MUIA_Text_HiChar, key,
  269.            MUIA_ControlChar, key,
  270.            MUIA_InputMode, MUIV_InputMode_RelVerify,
  271.            MUIA_Background, MUII_ButtonBack,
  272.            MUIA_Weight, 25,
  273.            End);
  274. }
  275.  
  276. APTR SimpleText(char *text);
  277.  
  278. APTR SimpleText(char *text)
  279. {
  280.   return(TextObject,
  281.           TextFrame,
  282.           MUIA_Text_Contents, text,
  283.           MUIA_InputMode,     MUIV_InputMode_None,
  284.           MUIA_Background,    MUII_TextBack,
  285.           End);
  286. }
  287.  
  288. static const char *distnames[]={"kilometer","mile",NULL};
  289.  
  290. static const char *distabbrevs[]={"km","mi",NULL};
  291.  
  292. static const char *speedabbrevs[]={"km/h","mph",NULL};
  293.  
  294. static const char *mpgabbrevs[]={"km/l","mpg",NULL};
  295.  
  296. static const char *fuelunits[]={"liter","gallon",NULL};
  297.  
  298. static const char *titles[]={"Average Speed", "Fuel Efficiency",
  299.   "Miscellaneous Prefs", NULL};
  300.  
  301. static const char *measurelabels[]={"Metric", "English", NULL};
  302.  
  303. static const char *displaylabels[]={
  304.   "All cities",
  305.   "Turns only",
  306.   "State lines and turns",
  307.   NULL
  308.   };
  309.  
  310. static const char *hiwaylabels[]={
  311.   "Rural Interstate",
  312.   "Suburban Interstate",
  313.   "Urban Interstate",
  314.   "Rural Highway (4 Lane)",
  315.   "Rural Highway (2 Lane)",
  316.   "Suburban Highway",
  317.   "Suburban Road",
  318.   "Urban Road",
  319.   "Rural Interstate (55)",
  320.   "Metro Interstate",
  321.   "Autoroute (Canada)",
  322.   "Main Highway (Canada)",
  323.   "Rural Motorway (UK)",
  324.   "Suburban Motorway (UK)",
  325.   "Urban Motorway (UK)",
  326.   "Primary 4 Lane (UK)",
  327.   "Primary 2 Lane (UK)",
  328.   "Other Route (UK)",
  329.   NULL
  330.   };
  331.  
  332. void ButtonBehave(APTR button, LONG notifyval);
  333.  
  334. void ButtonBehave(APTR button, LONG notifyval)
  335.   {
  336.   DoMethod((ULONG *)button,MUIM_Notify,MUIA_Pressed,FALSE,app,2,
  337.     MUIM_Application_ReturnID, notifyval);
  338.   }
  339.  
  340. void StringBehave(APTR string, LONG notifyval);
  341.  
  342. void StringBehave(APTR string, LONG notifyval)
  343.   {
  344.   DoMethod((ULONG *)string,MUIM_Notify,MUIA_String_Acknowledge,
  345.     MUIV_EveryTime, app, 2, MUIM_Application_ReturnID, notifyval);
  346.   }
  347.  
  348. void CycleBehave(APTR cycle, LONG notifyval);
  349.  
  350. void CycleBehave(APTR cycle, LONG notifyval)
  351.   {
  352.   DoMethod((ULONG *)cycle,MUIM_Notify,MUIA_Cycle_Active,
  353.     MUIV_EveryTime, app, 2, MUIM_Application_ReturnID, notifyval);
  354.   }
  355.  
  356. void DoStuff(ULONG i, ULONG gnum);
  357.  
  358. void DoStuff(ULONG i, ULONG gnum)
  359. {
  360.   APTR tempobj;
  361.   
  362.   tempobj=Label2(hiwaylabels[i]);
  363.   
  364.   ST_Speed[i]=StringObject,
  365.     StringFrame,
  366.     MUIA_String_MaxLen, 5,
  367.     MUIA_String_Integer, Speed[i],
  368.     MUIA_String_Accept, "0123456789",
  369.     MUIA_String_Format, MUIV_String_Format_Right,
  370.     MUIA_ExportID,      (i+100),
  371.     End;
  372.   
  373.   LB_Speed[i]=DLabel(speedabbrevs[MeasureUnits]);
  374.   
  375.   DoMethod((ULONG *)GP_Speed[gnum],OM_ADDMEMBER,tempobj);
  376.   DoMethod((ULONG *)GP_Speed[gnum],OM_ADDMEMBER,ST_Speed[i]);
  377.   DoMethod((ULONG *)GP_Speed[gnum],OM_ADDMEMBER,LB_Speed[i]);
  378.   
  379.   tempobj=Label2(hiwaylabels[i]);
  380.   
  381.   ST_MPG[i]=StringObject,
  382.     StringFrame,
  383.     MUIA_String_MaxLen, 5,
  384.     MUIA_String_Integer, MPG[i],
  385.     MUIA_String_Accept, "0123456789",
  386.     MUIA_String_Format, MUIV_String_Format_Right,
  387.     MUIA_ExportID,      (i+200),
  388.     End;
  389.   
  390.   LB_MPG[i]=DLabel(mpgabbrevs[MeasureUnits]);
  391.   
  392.   DoMethod((ULONG *)GP_MPG[gnum],OM_ADDMEMBER,tempobj);
  393.   DoMethod((ULONG *)GP_MPG[gnum],OM_ADDMEMBER,ST_MPG[i]);
  394.   DoMethod((ULONG *)GP_MPG[gnum],OM_ADDMEMBER,LB_MPG[i]);
  395. }
  396.  
  397. void main(int argc, char **argv)
  398. {
  399.   // This is the "main loop" function. It handles the application main
  400.   // window, calls the ChooseCity and ChangePrefs routines, and calls 
  401.   // the router and I/O routine, Navigate.
  402.   APTR CY_Display, CB_Debug;
  403.   
  404.   ULONG from=-1, to=-1, via[MAXVIA], viacount=0; // Array of city identifiers
  405.   // Miscellaneous prefs
  406.   
  407.   ULONG DefMeasureUnits=UNITS_ENGLISH, OldUnits;
  408.   ULONG DefSpeed[ROUTETYPES]={65,55,40,52,50,40,30,25,60,30,62,56,70,60,
  409.     50,65,50,40};
  410.   ULONG DefMPG[ROUTETYPES]={22,21,19,20,19,17,16,15,21,17,22,21,22,21,20,
  411.     18,17,16};
  412.   ULONG DefDefaultMPG=19;
  413.   UWORD DefDisplayType=DIS_ROUTECHANGE;
  414.   BOOL DefDebugOutput=FALSE, fullinfo=FALSE;
  415.   
  416.   struct MUIP_Window_SetCycleChain *scc;
  417.   
  418.   static struct CityData *cd;
  419.   static struct RouteData *rd;
  420.   
  421.   static char *DefDBase="Basic-USA.route",DBase[256],*tempstr;
  422.   static char filename[256]="", CurrentDBase[256];
  423.   BOOL going=TRUE, ok;
  424.   ULONG i, sigs, temp;
  425.   
  426.   for(i=0;i<MAXVIA;i++) via[i]=-1;
  427.   
  428.   strcpy(DBase,DefDBase);
  429.   MeasureUnits=DefMeasureUnits;
  430.   memcpy(Speed,DefSpeed,sizeof(Speed));
  431.   memcpy(MPG,DefMPG,sizeof(Speed));
  432.   DefaultMPG=DefDefaultMPG;
  433.   DisplayType=DefDisplayType;
  434.   debugoutput=DefDebugOutput;
  435.   
  436.   if(!argc)
  437.     {
  438.     argc=_WBArgc;
  439.     argv=_WBArgv;
  440.     }
  441.   
  442.   app=ApplicationObject,
  443.         MUIA_Application_Title,      "RoutePlanner",
  444.         MUIA_Application_Version,    "$VER: "VERS" ("DATE")",
  445.         MUIA_Application_Copyright,  "Copyright (C) 1994 Chris Lawrence",
  446.         MUIA_Application_Author,     "Chris Lawrence",
  447.         MUIA_Application_Description,"Highway Trip Planner",
  448.         MUIA_Application_Base,       "ROUTEPLANNER",
  449.         MUIA_Application_SingleTask, FALSE,
  450.         MUIA_Application_DiskObject,
  451.           disko=GetDiskObjectNew("PROGDIR:RoutePlanner"),
  452.         MUIA_Application_HelpFile,   "PROGDIR:RoutePlanner.guide",
  453.         // MUIA_Application_Commands, COMMANDS,
  454.         
  455.         SubWindow,
  456.         mainwindow=WindowObject,
  457.           MUIA_Window_Title,       VERS,
  458.           MUIA_Window_ID,          'RPLN',
  459.           MUIA_Window_Menustrip,   MakeMenustrip(mainmenu),
  460.           MUIA_Window_ScreenTitle, COPYRIGHT,
  461.           MUIA_HelpNode,           "MainWindow",
  462.           
  463.           WindowContents,
  464.           VGroup,
  465.             Child,VGroup,
  466.               Child,ColGroup(2),
  467.                 Child,BT_FromCity=KeyButton("From...",'f'),
  468.                 Child,TX_FromCity=SimpleText(""),
  469.                 Child,BT_ToCity=KeyButton("To...",'t'),
  470.                 Child,TX_ToCity=SimpleText(""),
  471.                 End,
  472.               Child,VGroup,
  473.                 MUIA_HelpNode, "ViaCities",
  474.                 GroupFrameT("Via"),
  475.                 Child,LV_ViaList=ListviewObject,
  476.                   MUIA_Listview_List, LI_ViaList=ListObject,
  477.                     InputListFrame,
  478.                     MUIA_List_CompareHook, &comphook,
  479.                     MUIA_List_ConstructHook, &consthook,
  480.                     MUIA_List_DestructHook, &desthook,
  481.                     MUIA_List_DisplayHook, &disphook,
  482.                     End,
  483.                   MUIA_Listview_MultiSelect, MUIV_Listview_MultiSelect_None,
  484.                   End,
  485.                 Child,HGroup,
  486.                   Child, HGroup,
  487.                     MUIA_Group_SameSize, TRUE,
  488.                     Child,BT_AddCity=KeyButton("Add...",'a'),
  489.                     Child,BT_ChangeCity=KeyButton("Change...",'c'),
  490.                     Child,BT_RemoveCity=KeyButton("Remove",'r'),
  491.                     End,
  492.                   Child, HGroup,
  493.                     MUIA_Weight, 0,
  494.                     Child,BT_MoveUp=KeyPopButton(MUII_ArrowUp,'u'),
  495.                     Child,BT_MoveDown=KeyPopButton(MUII_ArrowDown,'d'),
  496.                     End,
  497.                   End,
  498.                 End,
  499.               End,
  500.             Child,HGroup,
  501.               Child,BT_DoRoute=KeyButton("Plan Route...",'p'),
  502.               Child,BT_Quit=KeyButton("Quit RoutePlanner",'q'),
  503.               MUIA_Group_SameSize, TRUE,
  504.               End,
  505.             End,
  506.         End,
  507.         
  508.         SubWindow,
  509.         prefswindow=WindowObject,
  510.           MUIA_Window_Title,       "RoutePlanner Prefs",
  511.           MUIA_Window_ID,          'RPPR',
  512.           MUIA_Window_Menustrip,   MakeMenustrip(prefsmenu),
  513.           MUIA_Window_ScreenTitle, COPYRIGHT,
  514.           MUIA_HelpNode,           "PrefsWindow",
  515.           
  516.           WindowContents,
  517.           VGroup,
  518.             Child,REG_Prefs=RegisterGroup(titles),
  519.               MUIA_Register_Frame, TRUE,
  520.               Child, HGroup,
  521.                 Child, GP_Speed[0]=ColGroup(3),
  522.                   End,
  523.                 Child, MUI_MakeObject(MUIO_VBar,0),
  524.                 Child, GP_Speed[1]=ColGroup(3),
  525.                   End,
  526.                 End,
  527.               Child, HGroup,
  528.                 Child, GP_MPG[0]=ColGroup(3),
  529.                   End,
  530.                 Child, MUI_MakeObject(MUIO_VBar,0),
  531.                 Child, GP_MPG[1]=ColGroup(3),
  532.                   End,
  533.                 End,
  534.               Child, ColGroup(2),
  535.                 Child,KeyLabel2("Measurement",'m'),
  536.                 Child,CY_Measure=CycleObject,
  537.                   MUIA_Cycle_Entries,measurelabels,
  538.                   MUIA_ControlChar,'m',
  539.                   MUIA_ExportID, 30,
  540.                   MUIA_Cycle_Active,MeasureUnits,
  541.                   End,
  542.                 Child,KeyLabel2("Display",'i'),
  543.                 Child,CY_Display=CycleObject,
  544.                   MUIA_Cycle_Entries,displaylabels,
  545.                   MUIA_ControlChar,'i',
  546.                   MUIA_ExportID, 33,
  547.                   MUIA_Cycle_Active,DisplayType,
  548.                   End,
  549.                 Child,KeyLabel2("Default Fuel Efficiency",'f'),
  550.                 Child, HGroup,
  551.                   Child,ST_DefaultMPG=StringObject,
  552.                     StringFrame,
  553.                     MUIA_String_MaxLen, 5,
  554.                     MUIA_String_Integer, DefaultMPG,
  555.                     MUIA_String_Accept, "0123456789",
  556.                     MUIA_String_Format, MUIV_String_Format_Right,
  557.                     MUIA_ControlChar, 'f',
  558.                     MUIA_ExportID, 31,
  559.                     End,
  560.                   Child,LB_DefaultMPG=DLabel(mpgabbrevs[MeasureUnits]),
  561.                   End,
  562.                 Child,KeyLabel2("Default Database",'d'),
  563.                 Child,POP_DBase=PopaslObject,
  564.                   MUIA_Popstring_String,ST_DBase=StringObject,
  565.                     StringFrame,
  566.                     MUIA_ControlChar, 'd',
  567.                     MUIA_String_MaxLen, 255,
  568.                     MUIA_String_Contents, DBase,
  569.                     MUIA_ExportID, 32,
  570.                     End,
  571.                   MUIA_Popstring_Button,BT_DBase=PopButton(MUII_PopFile),
  572.                   ASLFR_TitleText, "Choose a database file...",
  573.                   End,
  574.                 Child,HSpace(0),
  575.                 Child,HGroup,
  576.                   Child, CB_Debug=KeyCheckMark(debugoutput,'b'),
  577.                   Child, KeyLLabel1("Debug output",'b'),
  578.                   Child, HSpace(0),
  579.                   End,
  580.                 End,
  581.               End,
  582.             Child,HGroup,
  583.               MUIA_Group_SameSize, TRUE,
  584.               Child,BT_SavePrefs=KeyButton("Save",'s'),
  585.               Child,BT_UsePrefs=KeyButton("Use",'u'),
  586.               Child,BT_CancelPrefs=KeyButton("Cancel",'c'),
  587.             End,
  588.           End,
  589.         End,
  590.       End;
  591.   
  592.   if(!app)
  593.     {
  594.     MUI_Request(NULL,NULL,0,NULL,"Ok","Could not create application.");
  595.     exit(20);
  596.     }
  597.   
  598.   for(i=0;i<ROUTETYPES;i++)
  599.     { // Add the speed gadgets
  600.     DoStuff(i,i/(ROUTETYPES/2));
  601.     }
  602.   
  603.   DoMethod((ULONG *)mainwindow,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
  604.     app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
  605.   
  606.   DoMethod((ULONG *)prefswindow,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
  607.     app,2,MUIM_Application_ReturnID,CANCELPREFS);
  608.   
  609.   DoMethod(LI_ViaList,MUIM_Notify,MUIA_List_Active,MUIV_EveryTime,
  610.     app,2,MUIM_Application_ReturnID,VIALIST);
  611.   
  612.   DoMethod(LV_ViaList,MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,
  613.     app,2,MUIM_Application_ReturnID,CHANGECITY);
  614.   
  615.   ButtonBehave(BT_FromCity, FROMCITY);
  616.   ButtonBehave(BT_ToCity, TOCITY);
  617.   ButtonBehave(BT_AddCity, ADDCITY);
  618.   ButtonBehave(BT_ChangeCity, CHANGECITY);
  619.   ButtonBehave(BT_RemoveCity, REMOVECITY);
  620.   ButtonBehave(BT_MoveUp, MOVEUP);
  621.   ButtonBehave(BT_MoveDown, MOVEDOWN);
  622.   ButtonBehave(BT_DoRoute, DOROUTE);
  623.   ButtonBehave(BT_Quit, QUIT);
  624.   
  625.   ButtonBehave(BT_SavePrefs, SAVEPREFS);
  626.   ButtonBehave(BT_UsePrefs, USEPREFS);
  627.   ButtonBehave(BT_CancelPrefs, CANCELPREFS);
  628.   
  629.   // StringBehave(ST_DBase, DBASECHANGED);
  630.   
  631.   DoMethod((ULONG *)app,MUIM_Application_Load,
  632.     MUIV_Application_Load_ENV);
  633.   
  634.   get(CY_Measure,MUIA_Cycle_Active,&MeasureUnits);
  635.   
  636.   CycleBehave(CY_Measure, MEASURECHANGE);
  637.   
  638.   DoMethod((ULONG *)mainwindow,MUIM_Window_SetCycleChain,
  639.     LV_ViaList, BT_MoveUp, BT_MoveDown,NULL);
  640.   
  641.   scc=malloc(4*((2*ROUTETYPES)+7));
  642.   if(!scc)
  643.     {
  644.     MUI_Request(NULL,NULL,0,NULL,"Ok","Could not create application.");
  645.     exit(20);
  646.     }
  647.   
  648.   for(i=0;i<ROUTETYPES;i++)
  649.     {
  650.     scc->obj[i]=ST_Speed[i];
  651.     scc->obj[i+ROUTETYPES]=ST_MPG[i];
  652.     }
  653.   
  654.   i=ROUTETYPES*2;
  655.   
  656.   scc->obj[i++]=CY_Measure;
  657.   scc->obj[i++]=CY_Display;
  658.   scc->obj[i++]=ST_DefaultMPG;
  659.   scc->obj[i++]=ST_DBase;
  660.   scc->obj[i++]=BT_DBase;
  661.   scc->obj[i]=NULL;
  662.   
  663.   scc->id=MUIM_Window_SetCycleChain;
  664.   
  665.   DoMethodA(prefswindow,scc);
  666.   
  667.   free(scc);
  668.   
  669.   set(BT_DoRoute,MUIA_Disabled,TRUE);
  670.   set(BT_MoveUp,MUIA_Disabled,TRUE);
  671.   set(BT_MoveDown,MUIA_Disabled,TRUE);
  672.   set(BT_ChangeCity,MUIA_Disabled,TRUE);
  673.   set(BT_RemoveCity,MUIA_Disabled,TRUE);
  674.   set(BT_AddCity,MUIA_Disabled,TRUE);
  675.   set(LV_ViaList,MUIA_Disabled,TRUE);
  676.   
  677.   set(mainwindow,MUIA_Window_DefaultObject,LV_ViaList);
  678.   
  679.   if(argc>1)
  680.     {
  681.     tempstr=argv[argc-1];
  682.     }
  683.   else
  684.     {
  685.     get(ST_DBase,MUIA_String_Contents,&tempstr);
  686.     }
  687.   
  688.   ok=OpenDatabase(tempstr,&cd,&rd);
  689.   if(!ok)
  690.     {
  691.     MUI_Request(app,NULL,0,NULL,"_Ok","Couldn't open database\n%s",tempstr);
  692.     strcpy(CurrentDBase,"No database loaded");
  693.     }
  694.   else
  695.     {
  696.     if(dbi)
  697.       {
  698.       if(Stricmp(dbi->dbi_Author,""))
  699.         fullinfo=TRUE;
  700.       }
  701.     
  702.     strcpy(CurrentDBase,tempstr);
  703.     }
  704.   
  705.   set(mainwindow,MUIA_Window_Open,TRUE);
  706.   get(mainwindow,MUIA_Window_Open,&i);
  707.   if(!i)
  708.     {
  709.     MUI_Request(app,NULL,0,NULL,"_Ok","Couldn't open main window.");
  710.     exit(20);
  711.     }
  712.   
  713.   while(going)
  714.     {
  715.     switch(DoMethod(app,MUIM_Application_Input,&sigs))
  716.       { // Can't ignore MUIV_Application_ReturnID_Quit
  717.       case 0:
  718.         break;
  719.       
  720.       case MUIV_Application_ReturnID_Quit:
  721.         going=FALSE;
  722.         break;
  723.       
  724.       case ABOUT:
  725.         MUI_Request(app,mainwindow,0,NULL,(char *)"_Ok",
  726.           (char *)MUIX_C""
  727.           VERS" ("DATE")\n\n"
  728.           "A Highway Trip Planner based on\n"
  729.           "Jim Butterfield's "MUIX_U"RoadRoute"MUIX_N"\n\n"
  730.           "Modifications © 1994 Chris Lawrence\n"
  731.           "Freely redistributable\n\n"
  732.           "This application uses MUI\n"
  733.           "MUI is © 1993-94 Stefan Stuntz\n\n"
  734.           "Compiled on "__DATE__);
  735.         break;
  736.       
  737.       case INFO:
  738.         if(fullinfo)
  739.           {
  740.           MUI_Request(app,mainwindow,0,NULL,"_Ok",
  741.             "Database Information\n\n"
  742.             MUIX_PH"%s\n"MUIX_PT
  743.             "%ld Cities, %ld Routes\n\n"
  744.             "Written by:\n"
  745.             "%s (%s)",CurrentDBase,cdcount,rdcount,
  746.             dbi->dbi_Author,dbi->dbi_EMail);
  747.           }
  748.         else
  749.           {
  750.           MUI_Request(app,mainwindow,0,NULL,"_Ok",
  751.             "Database Information\n\n"
  752.             MUIX_PH"%s\n"MUIX_PT
  753.             "%ld Cities, %ld Routes",CurrentDBase,cdcount,rdcount);
  754.           }
  755.         break;
  756.       
  757.       case PREFS:
  758.         set(prefswindow,MUIA_Window_Open,TRUE);
  759.         get(prefswindow,MUIA_Window_Open,&i);
  760.         if(!i)
  761.           {
  762.           MUI_Request(app,mainwindow,0,NULL,"_Ok",
  763.             "Can't open Preferences window.");
  764.           }
  765.         break;
  766.       
  767.       case SAVEPREFS: // Do not break up
  768.         DoMethod((ULONG *)app,MUIM_Application_Save,
  769.           MUIV_Application_Save_ENVARC);
  770.         
  771.       case USEPREFS:  // Do not break up
  772.         DoMethod((ULONG *)app,MUIM_Application_Save,
  773.           MUIV_Application_Save_ENV);
  774.         set(prefswindow,MUIA_Window_Open,FALSE);
  775.         break;
  776.       
  777.       case CANCELPREFS:
  778.         DoMethod((ULONG *)app,MUIM_Application_Load,
  779.           MUIV_Application_Load_ENV);
  780.         set(prefswindow,MUIA_Window_Open,FALSE);
  781.         break;
  782.       
  783.       case HIDE:
  784.         set(app,MUIA_Application_Iconified,TRUE);
  785.         break;
  786.         
  787.       case OPEN:
  788.         if(GetFile(filename,FALSE,"Select new database..."))
  789.           {
  790.           strcpy(CurrentDBase,filename);
  791.           ok=OpenDatabase(CurrentDBase,&cd,&rd);
  792.           if(!ok)
  793.             {
  794.             MUI_Request(app,mainwindow,0,NULL,"_Ok",
  795.               "Couldn't open database\n%s",filename);
  796.             }
  797.           else
  798.             {
  799.             from=-1;
  800.             to=-1;
  801.             for(i=0;i<MAXVIA;i++)
  802.               via[i]=-1;
  803.             viacount=0;
  804.             
  805.             set(TX_FromCity,MUIA_Text_Contents,"");
  806.             set(TX_ToCity,MUIA_Text_Contents,"");
  807.             DoMethod(LI_ViaList,MUIM_List_Clear,NULL);
  808.             set(BT_DoRoute,MUIA_Disabled,TRUE);
  809.             set(BT_AddCity,MUIA_Disabled,TRUE);
  810.             set(LV_ViaList,MUIA_Disabled,TRUE);
  811.             
  812.             if(dbi)
  813.               {
  814.               if(Stricmp(dbi->dbi_Author,""))
  815.               fullinfo=TRUE;
  816.               }
  817.             }
  818.           }
  819.         break;
  820.       
  821.       case OPENPREFS:
  822.         if(GetFile(filename,FALSE,"Select a preferences file..."))
  823.           {
  824.           DoMethod((ULONG *)app,MUIM_Application_Load,filename);
  825.           }
  826.         break;
  827.       
  828.       case SAVEPREFSAS:
  829.         if(GetFile(filename,TRUE,"Save preferences as..."))
  830.           {
  831.           DoMethod((ULONG *)app,MUIM_Application_Save,filename);
  832.           }
  833.         break;
  834.       
  835.       case RESTOREPREFS:
  836.         DoMethod((ULONG *)app,MUIM_Application_Load,
  837.           MUIV_Application_Load_ENV);
  838.         get(CY_Measure,MUIA_Cycle_Active,&MeasureUnits);
  839.         break;
  840.       
  841.       case LASTSAVEDPREFS:
  842.         DoMethod((ULONG *)app,MUIM_Application_Load,
  843.           MUIV_Application_Load_ENVARC);
  844.         get(CY_Measure,MUIA_Cycle_Active,&MeasureUnits);
  845.         break;
  846.       
  847.       case RESETPREFS:
  848.         for(i=0;i<ROUTETYPES;i++)
  849.           {
  850.           setinteger(ST_Speed[i],DefSpeed[i]);
  851.           setinteger(ST_MPG[i],DefMPG[i]);
  852.           }
  853.         
  854.         setstring(ST_DBase,DefDBase);
  855.         setinteger(ST_DefaultMPG,DefDefaultMPG);
  856.         set(CY_Measure,MUIA_Cycle_Active,DefMeasureUnits);
  857.         MeasureUnits=DefMeasureUnits;
  858.         setcycle(CY_Display,DefDisplayType);
  859.         break;
  860.       
  861.       case FROMCITY:
  862.         i=ChooseCity(cd,cdcount,from,"Choose starting city...");
  863.         
  864.         if(i==(ULONG)-2)
  865.           DoMethod(app,MUIM_Application_ReturnID,QUIT);
  866.         
  867.         if(i<(ULONG)-2)
  868.           {
  869.           from=i;
  870.           
  871.           SPrintf(filename,"%s, %s",cd[from].CityName,cd[from].StateName);
  872.           set(TX_FromCity,MUIA_Text_Contents,filename);
  873.           }
  874.         
  875.         set(BT_DoRoute,MUIA_Disabled,(from==(ULONG)-1 || to==(ULONG)-1));
  876.         set(BT_AddCity,MUIA_Disabled,(from==(ULONG)-1 || to==(ULONG)-1));
  877.         break;
  878.         
  879.       case TOCITY:
  880.         i=ChooseCity(cd,cdcount,to,"Choose ending city...");
  881.         
  882.         if(i==(ULONG)-2)
  883.           DoMethod(app,MUIM_Application_ReturnID,QUIT);
  884.         
  885.         if(i<(ULONG)-2)
  886.           {
  887.           to=i;
  888.           
  889.           SPrintf(filename,"%s, %s",cd[to].CityName,cd[to].StateName);
  890.           set(TX_ToCity,MUIA_Text_Contents,filename);
  891.           }
  892.         
  893.         set(BT_DoRoute,MUIA_Disabled,(from==(ULONG)-1 || to==(ULONG)-1));
  894.         set(BT_AddCity,MUIA_Disabled,(from==(ULONG)-1 || to==(ULONG)-1));
  895.         break;
  896.         
  897.       case DOROUTE:
  898.         if(from==to && viacount==0)
  899.           {
  900.           MUI_Request(app,mainwindow,0,NULL,"_Ok",
  901.             "You must travel through at least two cities.");
  902.           }
  903.         else
  904.           {
  905.           for(i=0;i<ROUTETYPES;i++)
  906.             {
  907.             get(ST_Speed[i],MUIA_String_Integer,&Speed[i]);
  908.             get(ST_MPG[i],MUIA_String_Integer,&MPG[i]);
  909.             }
  910.           
  911.           get(ST_DefaultMPG,MUIA_String_Integer,&DefaultMPG);
  912.           get(CY_Measure,MUIA_Cycle_Active,&MeasureUnits);
  913.           get(CY_Display,MUIA_Cycle_Active,&DisplayType);
  914.           get(CB_Debug,MUIA_Selected,&debugoutput);
  915.           
  916.           if(NavCoord(cd,rd,from,to,via,viacount)) going=FALSE;
  917.           }
  918.         break;
  919.       
  920.       case VIALIST:
  921.         get(LI_ViaList,MUIA_List_Active,&i);
  922.         
  923.         set(BT_ChangeCity,MUIA_Disabled,(i==MUIV_List_Active_Off));
  924.         set(BT_RemoveCity,MUIA_Disabled,(i==MUIV_List_Active_Off));
  925.         set(BT_MoveUp,MUIA_Disabled,(i==MUIV_List_Active_Off || i==0));
  926.         set(BT_MoveDown,MUIA_Disabled,(i==MUIV_List_Active_Off || i==viacount-1));
  927.         break;
  928.       
  929.       case ADDCITY:
  930.         if(viacount<MAXVIA)
  931.           {
  932.           via[viacount]=ChooseCity(cd,cdcount,-1,"Choose `via' city...");
  933.           if(via[viacount]==(ULONG)-2)
  934.             DoMethod(app,MUIM_Application_ReturnID,QUIT);
  935.           
  936.           if(via[viacount]<(ULONG)-2)
  937.             {
  938.             DoMethod(LI_ViaList,MUIM_List_InsertSingle,&cd[via[viacount]],
  939.               MUIV_List_Insert_Bottom);
  940.             DoMethod(app,MUIM_Application_ReturnID,VIALIST);
  941.             
  942.             set(LV_ViaList,MUIA_Disabled,FALSE);
  943.             viacount++;
  944.             }
  945.           }
  946.         else
  947.           MUI_Request(app,mainwindow,0,NULL,"_Ok","There is a maximum of\n"
  948.             "%ld `via' destinations.",MAXVIA);
  949.         break;
  950.       
  951.       case CHANGECITY:
  952.         get(LI_ViaList,MUIA_List_Active,&temp);
  953.         if(temp!=MUIV_List_Active_Off)
  954.           {
  955.           i=ChooseCity(cd,cdcount,via[temp],"Choose `via' city...");
  956.           if(i==(ULONG)-2)
  957.             DoMethod(app,MUIM_Application_ReturnID,QUIT);
  958.           
  959.           if(i<(ULONG)-2)
  960.             {
  961.             DoMethod(LI_ViaList,MUIM_List_Remove,temp);
  962.             DoMethod(LI_ViaList,MUIM_List_InsertSingle,&cd[i],temp);
  963.             via[temp]=i;
  964.             set(LI_ViaList,MUIA_List_Active,temp);
  965.             }
  966.           }
  967.         break;
  968.       
  969.       case REMOVECITY:
  970.         get(LI_ViaList,MUIA_List_Active,&temp);
  971.         if(temp!=MUIV_List_Active_Off)
  972.           {
  973.           DoMethod(LI_ViaList,MUIM_List_Remove,temp);
  974.           for(i=temp+1;i<viacount;i++)
  975.             via[i-1]=via[i];
  976.           via[viacount-1]=-1;
  977.           
  978.           viacount--;
  979.           
  980.           if(!viacount) set(LV_ViaList,MUIA_Disabled,TRUE);
  981.           }
  982.         break;
  983.       
  984.       case MOVEUP:
  985.         get(LI_ViaList,MUIA_List_Active,&temp);
  986.         if(temp!=MUIV_List_Active_Off && temp>0)
  987.           {
  988.           DoMethod(LI_ViaList,MUIM_List_Exchange,temp,temp-1);
  989.           i=via[temp];
  990.           via[temp]=via[temp-1];
  991.           via[temp-1]=i;
  992.           set(LI_ViaList,MUIA_List_Active,temp-1);
  993.           }
  994.         break;
  995.       
  996.       case MOVEDOWN:
  997.         get(LI_ViaList,MUIA_List_Active,&temp);
  998.         if(temp!=MUIV_List_Active_Off && temp<viacount-1)
  999.           {
  1000.           DoMethod(LI_ViaList,MUIM_List_Exchange,temp,temp+1);
  1001.           i=via[temp];
  1002.           via[temp]=via[temp+1];
  1003.           via[temp+1]=i;
  1004.           set(LI_ViaList,MUIA_List_Active,temp+1);
  1005.           }
  1006.         break;
  1007.       
  1008.       case MEASURECHANGE:
  1009.         OldUnits=MeasureUnits;
  1010.         get(CY_Measure,MUIA_Cycle_Active,&MeasureUnits);
  1011.         
  1012.         get(CY_Measure,MUIA_Cycle_Active,&MeasureUnits);
  1013.         get(ST_DefaultMPG,MUIA_String_Integer,&DefaultMPG);
  1014.         DefaultMPG=ConvertEfficiency(DefaultMPG,OldUnits,MeasureUnits);
  1015.         set(ST_DefaultMPG,MUIA_String_Integer,DefaultMPG);
  1016.         set(LB_DefaultMPG,MUIA_Text_Contents,mpgabbrevs[MeasureUnits]);
  1017.         
  1018.         for(i=0;i<ROUTETYPES;i++)
  1019.           {
  1020.           get(ST_Speed[i],MUIA_String_Integer,&Speed[i]);
  1021.           get(ST_MPG[i],MUIA_String_Integer,&MPG[i]);
  1022.           
  1023.           Speed[i]=ConvertDist(Speed[i],OldUnits,MeasureUnits);
  1024.           MPG[i]=ConvertEfficiency(MPG[i],OldUnits,MeasureUnits);
  1025.           
  1026.           set(ST_Speed[i],MUIA_String_Integer,Speed[i]);
  1027.           set(ST_MPG[i],MUIA_String_Integer,MPG[i]);
  1028.           
  1029.           set(LB_Speed[i],MUIA_Text_Contents,speedabbrevs[MeasureUnits]);
  1030.           set(LB_MPG[i],MUIA_Text_Contents,mpgabbrevs[MeasureUnits]);
  1031.           }
  1032.         break;
  1033.       }
  1034.     
  1035.     if(going && sigs) sigs=Wait(sigs | SIGBREAKF_CTRL_C);
  1036.     
  1037.     if(sigs & SIGBREAKF_CTRL_C) going=FALSE;
  1038.     }
  1039.   
  1040.   set(prefswindow,MUIA_Window_Open,FALSE);
  1041.   set(mainwindow,MUIA_Window_Open,FALSE);
  1042.   exit(0);
  1043. }
  1044.  
  1045. BOOL GetFile(char *filename, BOOL saverequest, char *tbar)
  1046. {
  1047.   struct FileRequester *fr;
  1048.   struct Window *win;
  1049.   BOOL result;
  1050.   
  1051.   fr=MUI_AllocAslRequest(ASL_FileRequest,NULL);
  1052.   if(!fr) return FALSE;
  1053.   
  1054.   get(mainwindow,MUIA_Window_Window,&win);
  1055.   
  1056.   set(app,MUIA_Application_Sleep,TRUE);
  1057.   
  1058.   if(MUI_AslRequestTags(fr,
  1059.     ASLFR_Window, win,
  1060.     ASLFR_TitleText, tbar,
  1061.     ASLFR_Flags1, (saverequest ? FRF_DOSAVEMODE : 0),
  1062.     ASLFR_RejectIcons, TRUE,
  1063.     TAG_DONE))
  1064.     {
  1065.     strcpy(filename,fr->fr_Drawer);
  1066.     AddPart(filename,fr->fr_File,255);
  1067.     
  1068.     result=TRUE;
  1069.     }
  1070.   else
  1071.     {
  1072.     result=FALSE;
  1073.     }
  1074.  
  1075.   set(app,MUIA_Application_Sleep,FALSE);
  1076.   
  1077.   if(fr) MUI_FreeAslRequest(fr);
  1078.   
  1079.   return result;
  1080. }
  1081.  
  1082. BOOL OpenDatabase(char *filename, struct CityData **cd,
  1083.   struct RouteData **rd)
  1084. {
  1085.   APTR oldmemptr;
  1086.   BPTR fhandle;
  1087.   __aligned struct FileInfoBlock fib;
  1088.   ULONG *temp, i, col;
  1089.   
  1090.   fhandle=Open(filename,MODE_OLDFILE);
  1091.   if(!fhandle) return FALSE;
  1092.   
  1093.   if(!ExamineFH(fhandle,&fib))
  1094.     {
  1095.     Close(fhandle);
  1096.     return FALSE;
  1097.     }
  1098.   
  1099.   oldmemptr=memptr;
  1100.   memptr=malloc(fib.fib_Size);
  1101.   if(!memptr)
  1102.     {
  1103.     Close(fhandle);
  1104.     return FALSE;
  1105.     }
  1106.   
  1107.   if(app)
  1108.     {
  1109.     set(app,MUIA_Application_Sleep,TRUE);
  1110.     }
  1111.   
  1112.   FRead(fhandle,memptr,1,fib.fib_Size);
  1113.   Close(fhandle);
  1114.   
  1115.   temp=(ULONG *)memptr;
  1116.   if((*temp)!='RPL2')
  1117.     {
  1118.     if(app)
  1119.       {
  1120.       set(app,MUIA_Application_Sleep,FALSE);
  1121.       }
  1122.   
  1123.     return FALSE;
  1124.     }
  1125.   
  1126.   if(oldmemptr) free(oldmemptr);
  1127.   
  1128.   *cd=(struct CityData *)((char *)memptr+12);
  1129.   temp=(ULONG *)((char *)(*cd)-4);
  1130.   cdcount=*temp;
  1131.   
  1132.   *rd=(struct RouteData *)
  1133.     ((char *)memptr+(sizeof(struct CityData)*(cdcount)+20));
  1134.   
  1135.   temp=(ULONG *)((char *)(*rd)-4);
  1136.   rdcount=*temp;
  1137.   
  1138.   // Parse the files
  1139.   for(i=0;i<cdcount;i++)
  1140.     (*cd)[i].RoadList=NULL;
  1141.   
  1142.   for(i=0;i<rdcount;i++)
  1143.     {
  1144.     struct RouteData *Route;
  1145.     
  1146.     Route=&((*rd)[i]);
  1147.     
  1148.     for(col=0;col<2;col++)
  1149.       {
  1150.       struct CityData *FoundCity;
  1151.       
  1152.       FoundCity=&((*cd)[Route->CityID[col]]);
  1153.       
  1154.       Route->CityNum[col]=FoundCity;
  1155.       Route->RLink[col]=FoundCity->RoadList;
  1156.       Route->Colm[col]=FoundCity->Colum;
  1157.       FoundCity->RoadList=Route;
  1158.       FoundCity->Colum=col;
  1159.       }
  1160.     }
  1161.   
  1162.   temp=(ULONG *)memptr;
  1163.   
  1164.   dbi=(struct DataBaseInfo *)
  1165.     ((char *)memptr+(sizeof(struct CityData)*(cdcount)+
  1166.     sizeof(struct RouteData)*(rdcount)+20));
  1167.   
  1168.   if(app)
  1169.     {
  1170.     set(app,MUIA_Application_Sleep,FALSE);
  1171.     }
  1172.   
  1173.   if(dbi->dbi_Security!=DoFunkyThing(cdcount+rdcount+dbi->dbi_AuthorCode+
  1174.     StringSum(dbi->dbi_Author)+StringSum(dbi->dbi_EMail)))
  1175.     {
  1176.     free(memptr);
  1177.     memptr=NULL;
  1178.     cdcount=0;
  1179.     rdcount=0;
  1180.     
  1181.     return FALSE;
  1182.     }
  1183.   
  1184.   return TRUE;
  1185. }
  1186.  
  1187. #define CANCEL   (30)
  1188. #define OK       (31)
  1189. #define STRING   (32)
  1190. #define CHANGELV (33)
  1191. #define ALL      (34)
  1192.  
  1193. ULONG ChooseCity(struct CityData *cd, ULONG CityCount, ULONG CurrentCity,
  1194.   char *tbar)
  1195. {
  1196.   // Present requester for choosing a city.
  1197.   // Return -2 if quit request received.
  1198.   // Return -1 if canceled
  1199.   
  1200.   APTR citywindow, LV_Listview, BT_All, BT_Ok, BT_Cancel, ST_CityName;
  1201.   APTR tempptr;
  1202.   BOOL going=TRUE, exact;
  1203.   ULONG sigs, choice, temp, i, found, entries;
  1204.   static struct CityName *cn;
  1205.   static char *tmp, cbuf[514], sbuf[128], compstr[256];
  1206.   
  1207.   set(app,MUIA_Application_Sleep,TRUE);
  1208.   
  1209.   citywindow=WindowObject,
  1210.                MUIA_Window_Title,       tbar,
  1211.                MUIA_Window_ScreenTitle, COPYRIGHT,
  1212.                MUIA_Window_RefWindow,   mainwindow,
  1213.                MUIA_Window_NoMenus,     TRUE,
  1214.                MUIA_Window_LeftEdge,    MUIV_Window_LeftEdge_Moused,
  1215.                MUIA_Window_TopEdge,     MUIV_Window_TopEdge_Moused,
  1216.                MUIA_Window_Height,      MUIV_Window_Height_Default,
  1217.                MUIA_HelpNode,           "CityRequester",
  1218.                
  1219.                WindowContents,
  1220.                VGroup,
  1221.                  Child,LV_Listview=ListviewObject,
  1222.                    MUIA_Listview_List,ListObject,
  1223.                      MUIA_List_CompareHook, &comphook,
  1224.                      MUIA_List_ConstructHook, &consthook,
  1225.                      MUIA_List_DestructHook, &desthook,
  1226.                      MUIA_List_DisplayHook, &disphook,
  1227.                      MUIA_List_AdjustWidth, TRUE,
  1228.                      InputListFrame,
  1229.                      End,
  1230.                    MUIA_Listview_MultiSelect, MUIV_Listview_MultiSelect_None,
  1231.                    End,
  1232.                  Child,HGroup,
  1233.                    Child, KeyLLabel2("Search:",'s'),
  1234.                    Child, ST_CityName=KeyString("",70,'s'),
  1235.                    Child, BT_All=KeyButton("All",'a'),
  1236.                    End,
  1237.                  Child,HGroup,
  1238.                    Child, BT_Ok=KeyButton("Ok",'o'),
  1239.                    Child, BT_Cancel=KeyButton("Cancel",'c'),
  1240.                    MUIA_Group_SameSize, TRUE,
  1241.                    End,
  1242.                  End,
  1243.                End;
  1244.   
  1245.   if(citywindow)
  1246.     {
  1247.     DoMethod(app,OM_ADDMEMBER,citywindow);
  1248.     
  1249.     DoMethod(citywindow,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
  1250.       app,2,MUIM_Application_ReturnID,CANCEL);
  1251.     
  1252.     DoMethod(LV_Listview,MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,
  1253.       app,2,MUIM_Application_ReturnID,OK);
  1254.     
  1255.     ButtonBehave(BT_Ok, OK);
  1256.     ButtonBehave(BT_All, ALL);
  1257.     ButtonBehave(BT_Cancel, CANCEL);
  1258.     
  1259.     DoMethod(LV_Listview,MUIM_Notify,MUIA_List_Active,MUIV_EveryTime,
  1260.       app,2,MUIM_Application_ReturnID,CHANGELV);
  1261.     
  1262.     // Add entries to list & sort them
  1263.     for(i=0;i<CityCount;i++)
  1264.       cd[i].Displayed=TRUE;
  1265.     
  1266.     AddListEntries(LV_Listview,cd,CityCount);
  1267.     
  1268.     if(CurrentCity==(ULONG)-1)
  1269.       {
  1270.       set(LV_Listview,MUIA_List_Active,MUIV_List_Active_Off);
  1271.       set(BT_Ok,MUIA_Disabled,TRUE);
  1272.       }
  1273.     else
  1274.       {
  1275.       BOOL found=FALSE;
  1276.       
  1277.       for(i=0;i<cdcount && !found;i++)
  1278.         {
  1279.         DoMethod(LV_Listview,MUIM_List_GetEntry,i,&cn);
  1280.         
  1281.         if(cn->cn_CityID==CurrentCity)
  1282.           {
  1283.           found=TRUE;
  1284.           set(LV_Listview,MUIA_List_Active,i);
  1285.           }
  1286.         }
  1287.       }
  1288.     
  1289.     DoMethod(citywindow,MUIM_Window_SetCycleChain,ST_CityName,
  1290.       LV_Listview,NULL);
  1291.     
  1292.     set(citywindow,MUIA_Window_DefaultObject,LV_Listview);
  1293.     
  1294.     set(citywindow,MUIA_Window_ActiveObject,ST_CityName);
  1295.     
  1296.     set(ST_CityName,MUIA_String_AttachedList,LV_Listview);
  1297.     
  1298.     StringBehave(ST_CityName,OK);
  1299.     
  1300.     set(citywindow,MUIA_Window_Open,TRUE);
  1301.     
  1302.     DoMethod(LV_Listview,MUIM_List_Jump,MUIV_List_Jump_Active);
  1303.     
  1304.     while(going)
  1305.       {
  1306.       switch(DoMethod(app,MUIM_Application_Input,&sigs))
  1307.         { // Can't ignore MUIV_Application_ReturnID_Quit
  1308.         case MUIV_Application_ReturnID_Quit:
  1309.           choice=(ULONG)-2;
  1310.           going=FALSE;
  1311.           break;
  1312.         
  1313.         case CANCEL:
  1314.           choice=(ULONG)-1;          
  1315.           going=FALSE;
  1316.           break;
  1317.           
  1318.         case CHANGELV:
  1319.           get(LV_Listview,MUIA_List_Active,&temp);
  1320.           set(BT_Ok,MUIA_Disabled,(temp==MUIV_List_Active_Off));
  1321.           if(temp!=MUIV_List_Active_Off)
  1322.             {
  1323.             DoMethod(LV_Listview,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,
  1324.               &cn);
  1325.             setstring(ST_CityName,cn->cn_Name);
  1326.             }
  1327.           break;
  1328.         
  1329.         case STRING:
  1330.           // Do search thingy
  1331.           get(ST_CityName,MUIA_String_Contents,&tmp);
  1332.           strcpy(cbuf,tmp);
  1333.           
  1334.           get(LV_Listview,MUIA_List_Entries,&entries);
  1335.           
  1336.           set(LV_Listview,MUIA_List_Active,MUIV_List_Active_Off);
  1337.           if(tmp=strchr(cbuf,','))
  1338.             {
  1339.             *tmp++='\0';
  1340.             while(*tmp==' ') tmp++;
  1341.             strcpy(sbuf,tmp);
  1342.             }
  1343.           else strcpy(sbuf,"");
  1344.           
  1345.           SPrintf(compstr,"%s#?,# %s#?",cbuf,sbuf);
  1346.           
  1347.           ParsePatternNoCase(compstr,cbuf,514);
  1348.           
  1349.           if(Stricmp(compstr,"#?,# #?"))
  1350.             {
  1351.             for(found=0,i=0,exact=FALSE;i<entries;i++)
  1352.               {
  1353.               DoMethod(LV_Listview,MUIM_List_GetEntry,i,&cn);
  1354.               if(cn)
  1355.                 {
  1356.                 if(MatchPatternNoCase(cbuf,cn->cn_Name))
  1357.                   {
  1358.                   cd[cn->cn_CityID].Displayed=TRUE;
  1359.                   found++;
  1360.                   choice=i;
  1361.                   
  1362.                   get(ST_CityName,MUIA_String_Contents,&tmp);
  1363.                   
  1364.                   if(!Stricmp(tmp,cn->cn_Name))
  1365.                     {
  1366.                     exact=TRUE;
  1367.                     temp=i;
  1368.                     }
  1369.                   }
  1370.                 else
  1371.                   cd[cn->cn_CityID].Displayed=FALSE;
  1372.                 }
  1373.               }
  1374.             }
  1375.           else
  1376.             {
  1377.             for(i=0;i<CityCount;i++)
  1378.               cd[i].Displayed=TRUE;
  1379.             found=2;
  1380.             }
  1381.           
  1382.           if(found==0)
  1383.             {
  1384.             setstring(ST_CityName,"");
  1385.             MUI_Request(app,citywindow,0,NULL,"_Ok","No cities matched");
  1386.             set(citywindow,MUIA_Window_ActiveObject,ST_CityName);
  1387.             }
  1388.           else if(found==1 || exact)
  1389.             {
  1390.             set(LV_Listview,MUIA_List_Active,(exact ? temp : choice));
  1391.             if(exact)
  1392.               {
  1393.               DoMethod(app,MUIM_Application_ReturnID,OK);
  1394.               set(citywindow,MUIA_Window_ActiveObject,LV_Listview);
  1395.               }
  1396.             else
  1397.               set(citywindow,MUIA_Window_ActiveObject,ST_CityName);
  1398.             }
  1399.           else
  1400.             {
  1401.             AddListEntries(LV_Listview,cd,CityCount);
  1402.             set(citywindow,MUIA_Window_ActiveObject,ST_CityName);
  1403.             }
  1404.           
  1405.           break;
  1406.         
  1407.         case ALL:
  1408.           for(i=0;i<CityCount;i++)
  1409.             {
  1410.             cd[i].Displayed=TRUE;
  1411.             }
  1412.           
  1413.           AddListEntries(LV_Listview,cd,CityCount);
  1414.           set(citywindow,MUIA_Window_ActiveObject,ST_CityName);
  1415.           break;
  1416.         
  1417.         case OK:
  1418.           get(citywindow,MUIA_Window_ActiveObject,&tempptr);
  1419.           if(tempptr==ST_CityName)
  1420.             {
  1421.             DoMethod(app,MUIM_Application_ReturnID,STRING);
  1422.             }
  1423.           else
  1424.             {
  1425.             DoMethod(LV_Listview,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&cn);
  1426.             if(cn)
  1427.               {
  1428.               get(ST_CityName,MUIA_String_Contents,&tmp);
  1429.               
  1430.               if(!Stricmp(cn->cn_Name,tmp))
  1431.                 {
  1432.                 choice=cn->cn_CityID;
  1433.                 going=FALSE;
  1434.                 }
  1435.               else
  1436.                 {
  1437.                 DoMethod(app,MUIM_Application_ReturnID,STRING);
  1438.                 }
  1439.               }
  1440.             }
  1441.           break;
  1442.         }
  1443.       
  1444.       if(going && sigs) Wait(sigs);
  1445.       }
  1446.     
  1447.     set(citywindow,MUIA_Window_Open,FALSE);
  1448.     DoMethod(app,OM_REMMEMBER,citywindow);
  1449.     MUI_DisposeObject(citywindow);
  1450.     }
  1451.   else
  1452.     MUI_RequestA(app,mainwindow,0,NULL,"_Ok","Couldn't create city requester.",NULL);
  1453.   
  1454.   set(app,MUIA_Application_Sleep,FALSE);
  1455.   return(choice);
  1456. }
  1457.  
  1458. void AddListEntries(APTR list, struct CityData *cd, ULONG CityCount)
  1459. {
  1460.   ULONG i;
  1461.   
  1462.   set(list,MUIA_List_Quiet,TRUE);
  1463.   
  1464.   DoMethod(list,MUIM_List_Clear,NULL);
  1465.   
  1466.   for(i=0;i<CityCount;i++)
  1467.     if(cd[i].Displayed && !cd[i].Intersection)
  1468.       DoMethod(list,MUIM_List_InsertSingle,&cd[i],MUIV_List_Insert_Bottom);
  1469.   
  1470.   DoMethod(list,MUIM_List_Sort,NULL);
  1471.   
  1472.   set(list,MUIA_List_Quiet,FALSE);
  1473. }
  1474.  
  1475. UWORD ConvertDist(UWORD srcDist, UWORD srcUnits, UWORD destUnits);
  1476. UWORD ConvertToTime(UWORD Code, UWORD SVal, UWORD Dist, UWORD RteUnits,
  1477.   UWORD SysUnits);
  1478.  
  1479. UWORD ConvertDist(UWORD srcDist, UWORD srcUnits, UWORD destUnits)
  1480. {
  1481.   ULONG work;
  1482.   
  1483.   if(srcUnits==UNITS_ENGLISH && destUnits==UNITS_METRIC)
  1484.     {
  1485.     work=(srcDist*16093)+8047;
  1486.     work/=10000;
  1487.     }
  1488.   else if(srcUnits==UNITS_METRIC && destUnits==UNITS_ENGLISH)
  1489.     {
  1490.     work=(srcDist*10000)+5000;
  1491.     work/=16093;
  1492.     }
  1493.   else work=srcDist;
  1494.   
  1495.   return (UWORD)work;
  1496. }
  1497.  
  1498. UWORD ConvertToTime(UWORD Code, UWORD SVal, UWORD Dist, UWORD RteUnits,
  1499.   UWORD SysUnits)
  1500. {
  1501.   float tval;
  1502.   
  1503.   if(Code==USE_TIME) return SVal;
  1504.   
  1505.   if(Code==USE_SPEED)
  1506.     {
  1507.     if(SVal==0) return 0;
  1508.     tval=60.0*Dist/SVal;
  1509.     }
  1510.   else
  1511.     {
  1512.     tval=60.0*ConvertDist(Dist,RteUnits,SysUnits)/Speed[Code-2];
  1513.     }
  1514.   
  1515.   return(UWORD)ceil(tval);
  1516. }
  1517.  
  1518. UWORD ConvertEfficiency(UWORD srcEff, UWORD srcUnits, UWORD destUnits)
  1519. {
  1520.   ULONG work;
  1521.   
  1522.   if(srcUnits==UNITS_ENGLISH && destUnits==UNITS_METRIC)
  1523.     {
  1524.     work=(srcEff*4251)+2126;
  1525.     work/=10000;
  1526.     }
  1527.   else if(srcUnits==UNITS_METRIC && destUnits==UNITS_ENGLISH)
  1528.     {
  1529.     work=(srcEff*10000)+5000;
  1530.     work/=4251;
  1531.     }
  1532.   else work=srcEff;
  1533.   
  1534.   return (UWORD)work;
  1535. }
  1536.  
  1537. // Trip stuff
  1538. #define VIEW_SAVEAS    (40) // Save the trip to disk
  1539. #define VIEW_PRINT    (41) // Print the trip
  1540. #define VIEW_CLOSE    (42) // Close the window
  1541. #define VIEW_QUIT    MUIV_Application_ReturnID_Quit
  1542.  
  1543. #define VIEW_TRIPCHNG    (43) // If user changes viewed trip
  1544. #define VIEW_CONTINUE    VIEW_CLOSE
  1545.  
  1546. struct NewMenu viewmenu[]={
  1547.   NM_TITLE,"Project",NULL,NULL,0L,NULL,
  1548.    NM_ITEM,"Save As...","S",NULL,0L,(APTR)VIEW_SAVEAS,
  1549.    NM_ITEM,"Print","P",NULL,0L,(APTR)VIEW_PRINT,
  1550.    NM_ITEM,NM_BARLABEL,NULL,NULL,0L,NULL,
  1551.    NM_ITEM,"Close Window","C",NULL,0L,(APTR)VIEW_CLOSE,
  1552.    NM_ITEM,"Quit RoutePlanner","Q",NULL,0L,(APTR)VIEW_QUIT,
  1553.   };
  1554.  
  1555. static char *triptypes[]={"shortest route","quickest route",NULL};
  1556.  
  1557. void PrintRoute(char *filename, struct CityData **point, UWORD points,
  1558.   BOOL isprinter);
  1559.  
  1560. BOOL NavCoord(struct CityData *cd, struct RouteData *rd,
  1561.   ULONG fromID, ULONG toID, ULONG *viaID, ULONG viacount)
  1562. //
  1563. // Navigation Coordination routine
  1564. {
  1565.   BOOL wasquit=FALSE, going=TRUE;
  1566.   struct CityData *point[MAXVIA+2], *SearchCity, *FLink;
  1567.   ULONG i, points, sigs;
  1568.   APTR navwindow;
  1569.   unsigned short Column, ColStart, ColEnd, TrackTrail;
  1570.   unsigned short NextCol, NewCol;
  1571.   struct RouteData *NextRoute, *NewRoute;
  1572.   static unsigned short Result[3][2];
  1573.   static char strbuff[300], tempstr[300], otstr[300];
  1574.   static struct TripEntry te;
  1575.   
  1576.   APTR TX_From,TX_To,TX_Via,VG_Trip[2];
  1577.   APTR CY_ChangeTrip,TX_Distance[2],TX_Time[2],TX_Fuel[2];
  1578.   APTR BT_Continue,GP_Trip,LB_Via;
  1579.   
  1580.   // Sleep windows
  1581.   set(app,MUIA_Application_Sleep,TRUE);
  1582.   
  1583.   for(i=0;i<MAXTRAIL;i++)
  1584.     {
  1585.     for(Column=0;Column<2;Column++)
  1586.       {
  1587.       Trail[i][Column].ct_City=NULL;
  1588.       Trail[i][Column].ct_Waypoint=CT_NOPOINT;
  1589.       }
  1590.     }
  1591.   
  1592.   // How many waypoints?
  1593.   point[0]=&cd[fromID];
  1594.   
  1595.   for(i=1;i<(viacount+1) && viaID[i-1]!=(ULONG)-1;i++)
  1596.     {
  1597.     point[i]=&cd[viaID[i-1]];
  1598.     }
  1599.   
  1600.   point[i]=&cd[toID];
  1601.   points=i+1;
  1602.   
  1603.   // Do navigation, with via list
  1604.   TrailPoint[0]=0;
  1605.   TrailPoint[1]=0;
  1606.   
  1607.   for(i=0;i<(points-1);i++)
  1608.     {
  1609.     Navigate(cd,point[i],point[i+1]);
  1610.     
  1611.     for(Column=0;Column<2;Column++)
  1612.       {
  1613.       if(TrailPoint[Column]) 
  1614.         Trail[TrailPoint[Column]-1][Column].ct_Waypoint=CT_WAYPOINT;
  1615.       }
  1616.     }
  1617.   
  1618.   for(Column=0; Column<2; Column++)
  1619.     {
  1620.     Result[0][Column]=0;   /* dist */
  1621.     Result[1][Column]=0;   /* time */
  1622.     Result[2][Column]=0;   // fuel
  1623.     SearchCity=point[0];
  1624.     
  1625.     for(TrackTrail=0; TrackTrail<TrailPoint[Column]; TrackTrail++)
  1626.       {
  1627.       ULONG mpg, truedist, truetime;
  1628.       
  1629.       FLink=Trail[TrackTrail][Column].ct_City;
  1630.       NextRoute=SearchCity->RoadList;
  1631.       NextCol=SearchCity->Colum;
  1632.       
  1633.       while (NextRoute && FLink != NextRoute->CityNum[1-NextCol]) 
  1634.         {
  1635.         NewRoute=NextRoute->RLink[NextCol];
  1636.         NewCol=NextRoute->Colm[NextCol];
  1637.         NextRoute=NewRoute;
  1638.         NextCol=NewCol;
  1639.         }
  1640.       
  1641.       if(NextRoute->SpeedCode>=INTERSTATE_RURAL)
  1642.         mpg=MPG[NextRoute->SpeedCode-2];
  1643.       else
  1644.         mpg=DefaultMPG;
  1645.       
  1646.       truedist=ConvertDist(NextRoute->Distance,NextRoute->Units,
  1647.         MeasureUnits);
  1648.       truetime=ConvertToTime(NextRoute->SpeedCode,NextRoute->Speed,
  1649.         NextRoute->Distance,NextRoute->Units,MeasureUnits);
  1650.       
  1651.       Result[2][Column]=Result[2][Column]+(((100*truedist)/mpg)+50)/100;
  1652.       Result[1][Column]=Result[1][Column]+truetime;
  1653.       Result[0][Column]=Result[0][Column]+truedist;
  1654.       SearchCity=FLink;
  1655.       }  /* next Link */
  1656.     }    /* next Column */
  1657.     
  1658.   ColStart=0;
  1659.   ColEnd=1;
  1660.   
  1661.   if(Result[0][0]==Result[0][1])
  1662.     {
  1663.     ColStart=1;
  1664.     ColEnd=1;
  1665.     }
  1666.   
  1667.   if(Result[1][0]==Result[1][1])
  1668.     {
  1669.     ColStart=0;
  1670.     ColEnd=0;
  1671.     }
  1672.   
  1673.   // Pop up a view window
  1674.   navwindow=WindowObject,
  1675.               MUIA_Window_Title, "RoutePlanner Trip",
  1676.               MUIA_Window_ScreenTitle, COPYRIGHT,
  1677.               MUIA_Window_ID, 3,
  1678.               MUIA_Window_Menustrip, MakeMenustrip(viewmenu),
  1679.               MUIA_HelpNode, "TripWindow",
  1680.               
  1681.               WindowContents,
  1682.               VGroup,
  1683.                 Child,ColGroup(2),
  1684.                   Child,Label2("From:"),
  1685.                   Child,TX_From=SimpleText(""),
  1686.                   Child,Label2("To:"),
  1687.                   Child,TX_To=SimpleText(""),
  1688.                   Child,LB_Via=Label2("Via:"),
  1689.                   Child,TX_Via=SimpleText(""),
  1690.                   End,
  1691.                 Child,VGroup,
  1692.                   GroupFrame,
  1693.                   Child,HGroup,
  1694.                     Child,KeyLLabel2("View",'v'),
  1695.                     Child,CY_ChangeTrip=KeyCycle(triptypes,'v'),
  1696.                     End,
  1697.                   Child,GP_Trip=VGroup,
  1698.                     MUIA_Group_PageMode, TRUE,
  1699.                     Child,VGroup,
  1700.                       Child,ColGroup(2),
  1701.                         Child,Label2("Distance:"),
  1702.                         Child,TX_Distance[0]=SimpleText(""),
  1703.                         Child,Label2("Time:"),
  1704.                         Child,TX_Time[0]=SimpleText(""),
  1705.                         Child,Label2("Fuel used:"),
  1706.                         Child,TX_Fuel[0]=SimpleText(""),
  1707.                         End,
  1708.                       Child,VG_Trip[0]=ListviewObject,
  1709.                         MUIA_Listview_Input, FALSE,
  1710.                         MUIA_Listview_List, ListObject,
  1711.                           ReadListFrame,
  1712.                           MUIA_Font, MUIV_Font_Fixed,
  1713.                           MUIA_List_ConstructHook, MUIV_List_ConstructHook_String,
  1714.                           MUIA_List_DestructHook, MUIV_List_DestructHook_String,
  1715.                           End,
  1716.                         End,
  1717.                       End,
  1718.                     Child,VGroup,
  1719.                       Child,ColGroup(2),
  1720.                         Child,Label2("Distance:"),
  1721.                         Child,TX_Distance[1]=SimpleText(""),
  1722.                         Child,Label2("Time:"),
  1723.                         Child,TX_Time[1]=SimpleText(""),
  1724.                         Child,Label2("Fuel used:"),
  1725.                         Child,TX_Fuel[1]=SimpleText(""),
  1726.                         End,
  1727.                       Child,VG_Trip[1]=ListviewObject,
  1728.                         MUIA_Listview_Input, FALSE,
  1729.                         MUIA_Listview_List, ListObject,
  1730.                           ReadListFrame,
  1731.                           MUIA_Font, MUIV_Font_Fixed,
  1732.                           MUIA_List_ConstructHook, MUIV_List_ConstructHook_String,
  1733.                           MUIA_List_DestructHook, MUIV_List_DestructHook_String,
  1734.                           End,
  1735.                         End,
  1736.                       End,
  1737.                     End,
  1738.                   End,
  1739.                 Child,BT_Continue=KeyButton("Continue",'c'),
  1740.                 End,
  1741.             End;
  1742.   
  1743.   if(!navwindow)
  1744.     {
  1745.     MUI_Request(app,mainwindow,0,NULL,"_Ok","Couldn't open trip window.");
  1746.     return FALSE;
  1747.     }
  1748.   
  1749.   DoMethod(app,OM_ADDMEMBER,navwindow);
  1750.   
  1751.   SPrintf(strbuff,"%s, %s",point[0]->CityName,point[0]->StateName);
  1752.   set(TX_From,MUIA_Text_Contents,strbuff);
  1753.   
  1754.   SPrintf(strbuff,"%s, %s",point[points-1]->CityName,
  1755.     point[points-1]->StateName);
  1756.   set(TX_To,MUIA_Text_Contents,strbuff);
  1757.   
  1758.   if(points>2)
  1759.     {
  1760.     strcpy(strbuff,"");
  1761.     for(i=1;i<(points-1);i++)
  1762.       {
  1763.       SPrintf(tempstr,"%s, %s",point[i]->CityName,point[i]->StateName);
  1764.       strncat(strbuff,tempstr,sizeof(strbuff));
  1765.       if(i<(points-2)) strncat(strbuff,"\n",sizeof(strbuff));
  1766.       }
  1767.     
  1768.     set(TX_Via,MUIA_Text_Contents,strbuff);
  1769.     }
  1770.   else
  1771.     {
  1772.     set(TX_Via,MUIA_Text_Contents,"Most direct route");
  1773.     }
  1774.   
  1775.   for(Column=ColStart; Column<=ColEnd; Column++)
  1776.     {
  1777.     UWORD dist=0, time=0, cumdist=0, cumtime=0;
  1778.     
  1779.     SearchCity=point[0];
  1780.     for(TrackTrail=0; TrackTrail<TrailPoint[Column]; TrackTrail++)
  1781.       {
  1782.       FLink=Trail[TrackTrail][Column].ct_City;
  1783.       NextRoute=SearchCity->RoadList;
  1784.       NextCol=SearchCity->Colum;
  1785.       
  1786.       while (NextRoute && FLink!=NextRoute->CityNum[1-NextCol]) 
  1787.         {
  1788.         NewRoute=NextRoute->RLink[NextCol];
  1789.         NewCol=NextRoute->Colm[NextCol];
  1790.         NextRoute=NewRoute;
  1791.         NextCol=NewCol;
  1792.         }   /* wend, no NextRoute */
  1793.       /*  Print highway link information */
  1794.       
  1795.       te.te_Distance=ConvertDist(NextRoute->Distance,NextRoute->Units,
  1796.         MeasureUnits);
  1797.       te.te_Time=ConvertToTime(NextRoute->SpeedCode,NextRoute->Speed,
  1798.         NextRoute->Distance,NextRoute->Units,MeasureUnits);
  1799.       te.te_Route=NextRoute->Hiway;
  1800.       
  1801.       if(Stricmp(NextRoute->Exits[1-NextCol],""))
  1802.         {
  1803.         SPrintf(tempstr,"%s (Exit %s)",FLink->CityName,
  1804.           NextRoute->Exits[1-NextCol]);
  1805.         te.te_End=tempstr;
  1806.         }
  1807.       else te.te_End=FLink->CityName;
  1808.       
  1809.       dist+=te.te_Distance;
  1810.       time+=te.te_Time;
  1811.       
  1812.       cumdist+=te.te_Distance;
  1813.       cumtime+=te.te_Time;
  1814.       
  1815.       if(Stricmp(SearchCity->StateName,FLink->StateName))
  1816.         {
  1817.         SPrintf(otstr,"CROSSING FROM %s TO %s",SearchCity->StateName,
  1818.           FLink->StateName);
  1819.         
  1820.         DoMethod(VG_Trip[Column],MUIM_List_InsertSingle,otstr,
  1821.           MUIV_List_Insert_Bottom);
  1822.         }
  1823.       
  1824.       if(TrackTrail+1<TrailPoint[Column] && DisplayType &&
  1825.         !Trail[TrackTrail][Column].ct_Waypoint)
  1826.         {
  1827.         NextRoute=FLink->RoadList;
  1828.         NextCol=FLink->Colum;
  1829.         FLink=Trail[TrackTrail+1][Column].ct_City;
  1830.         
  1831.         while (NextRoute && FLink!=NextRoute->CityNum[1-NextCol]) 
  1832.           {
  1833.           NewRoute=NextRoute->RLink[NextCol];
  1834.           NewCol=NextRoute->Colm[NextCol];
  1835.           NextRoute=NewRoute;
  1836.           NextCol=NewCol;
  1837.           }   /* wend, no NextRoute */
  1838.         
  1839.         FLink=Trail[TrackTrail][Column].ct_City;
  1840.         
  1841.         if(DisplayType==DIS_ROUTECHANGE)
  1842.           {
  1843.           if(!Stricmp(NextRoute->Hiway,te.te_Route))
  1844.             {
  1845.             SearchCity=FLink;
  1846.             continue;
  1847.             }
  1848.           }
  1849.         
  1850.         if(DisplayType==DIS_STATECHANGE)
  1851.           {
  1852.           if(!Stricmp(FLink->StateName,SearchCity->StateName) &&
  1853.             !Stricmp(NextRoute->Hiway,te.te_Route))
  1854.             {
  1855.             SearchCity=FLink;
  1856.             continue;
  1857.             }
  1858.           }
  1859.         }
  1860.       
  1861.       SPrintf(otstr,"%4ld %s (%2ld:%02ld) [%4ld %s (%2ld:%02ld)] %s to %s",
  1862.         dist,distabbrevs[MeasureUnits],time/60,time%60,
  1863.         cumdist,distabbrevs[MeasureUnits],cumtime/60,cumtime%60,
  1864.         te.te_Route,te.te_End);
  1865.       
  1866.       DoMethod(VG_Trip[Column],MUIM_List_InsertSingle,otstr,
  1867.         MUIV_List_Insert_Bottom);
  1868.       
  1869.       if(Trail[TrackTrail][Column].ct_Waypoint)
  1870.         {
  1871.         SPrintf(otstr,"ARRIVED %s, %s: %ld %s%s - %ld:%02ld",
  1872.           FLink->CityName,FLink->StateName,
  1873.           cumdist,distnames[MeasureUnits],(cumdist==1 ? "" : "s"),
  1874.           cumtime/60,cumtime%60);
  1875.         
  1876.         DoMethod(VG_Trip[Column],MUIM_List_InsertSingle,otstr,
  1877.           MUIV_List_Insert_Bottom);
  1878.         
  1879.         cumdist=0;
  1880.         cumtime=0;
  1881.         }
  1882.       
  1883.       dist=0;
  1884.       time=0;
  1885.       
  1886.       SearchCity=FLink;
  1887.       }  /* next link */
  1888.     
  1889.     SPrintf(strbuff,"%ld %s%s",Result[0][Column],distnames[MeasureUnits],
  1890.       (Result[0][Column]==1 ? "" : "s"));
  1891.     set(TX_Distance[Column],MUIA_Text_Contents,strbuff);
  1892.     
  1893.     SPrintf(strbuff,"%ld hour%s, %ld minute%s",Result[1][Column]/60,
  1894.       ((Result[1][Column]/60)==1 ? "" : "s"),
  1895.       Result[1][Column]%60,((Result[1][Column]%60)==1 ? "" : "s"));
  1896.     set(TX_Time[Column],MUIA_Text_Contents,strbuff);
  1897.     
  1898.     SPrintf(strbuff,"%ld %s%s",Result[2][Column],fuelunits[MeasureUnits],
  1899.       (Result[2][Column]==1 ? "" : "s"));
  1900.     set(TX_Fuel[Column],MUIA_Text_Contents,strbuff);
  1901.     }  /* next Column */
  1902.   
  1903.   ButtonBehave(BT_Continue,VIEW_CONTINUE);
  1904.   
  1905.   DoMethod(navwindow,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
  1906.     app,2,MUIM_Application_ReturnID,VIEW_CLOSE);
  1907.   
  1908.   DoMethod(CY_ChangeTrip,MUIM_Notify,MUIA_Cycle_Active,MUIV_EveryTime,
  1909.     GP_Trip,3,MUIM_Set,MUIA_Group_ActivePage,MUIV_TriggerValue);
  1910.   
  1911.   for(i=ColStart;i<=ColEnd;i++)
  1912.     DoMethod(CY_ChangeTrip,MUIM_Notify,MUIA_Cycle_Active,i,
  1913.       navwindow,3,MUIM_Set,MUIA_Window_ActiveObject,VG_Trip[i]);
  1914.   
  1915.   set(CY_ChangeTrip,MUIA_Cycle_Active,ColStart);
  1916.   
  1917.   if(ColStart==ColEnd) set(CY_ChangeTrip,MUIA_Disabled,TRUE);
  1918.   
  1919.   DoMethod(navwindow,MUIM_Window_SetCycleChain,VG_Trip[0],
  1920.     VG_Trip[1],NULL);
  1921.   
  1922.   set(navwindow,MUIA_Window_ActiveObject,VG_Trip[ColStart]);
  1923.   
  1924.   set(navwindow,MUIA_Window_Open,TRUE);
  1925.   // Window event loop
  1926.   
  1927.   while(going)
  1928.       {
  1929.       switch(DoMethod(app,MUIM_Application_Input,&sigs))
  1930.         { // Can't ignore MUIV_Application_ReturnID_Quit
  1931.         case MUIV_Application_ReturnID_Quit:
  1932.           wasquit=TRUE;
  1933.           going=FALSE;
  1934.           break;
  1935.         
  1936.         case VIEW_CLOSE:
  1937.           going=FALSE;
  1938.           break;
  1939.           
  1940.         case VIEW_SAVEAS:
  1941.           set(navwindow,MUIA_Window_Sleep,TRUE);
  1942.           if(GetFile(strbuff,TRUE,"Save directions as..."))
  1943.             {
  1944.             PrintRoute(strbuff,point,points,FALSE);
  1945.             }
  1946.           set(navwindow,MUIA_Window_Sleep,FALSE);
  1947.           break;
  1948.         
  1949.         case VIEW_PRINT:
  1950.           set(navwindow,MUIA_Window_Sleep,TRUE);
  1951.           PrintRoute("PRT:",point,points,TRUE);
  1952.           set(navwindow,MUIA_Window_Sleep,FALSE);
  1953.           break;
  1954.         }
  1955.       
  1956.       if(going && sigs) Wait(sigs);
  1957.       }
  1958.   
  1959.   set(navwindow,MUIA_Window_Open,FALSE);
  1960.   DoMethod(app,OM_REMMEMBER,navwindow);
  1961.   MUI_DisposeObject(navwindow);
  1962.   
  1963.   set(app,MUIA_Application_Sleep,FALSE);
  1964.   return wasquit;
  1965. }
  1966.  
  1967. void Navigate(struct CityData *cd, struct CityData *Start,
  1968.   struct CityData *Finish)
  1969. {
  1970. // This is almost straight out of Jim's code.
  1971. // Only thing different is the maximum trail length; RoutePlanner
  1972. //   allows a much longer trail
  1973.   
  1974.   ULONG i;
  1975.   unsigned short Column, Travel;
  1976.   unsigned short NextCol, NewCol;
  1977.   struct CityData *BLink, *SearchCity;
  1978.   struct CityData *ELink, *FLink, *OtherCity;
  1979.   struct RouteData *NextRoute, *NewRoute;
  1980.   static unsigned short MiniVal;
  1981.   static unsigned short ThisDist[2];
  1982.   
  1983.   for(i=0; i<cdcount; i++)
  1984.     {
  1985.     cd[i].WorkList = NULL;
  1986.     for(Column=0; Column<2; Column++)
  1987.       {
  1988.       cd[i].MinDist[Column]=65535;
  1989.       cd[i].NextCity[Column]=NULL;
  1990.       }
  1991.     }
  1992.   
  1993.   ELink=Finish;
  1994.   MiniVal=0;
  1995.   
  1996.   for(Column=0; Column<2; Column++)
  1997.     {
  1998.     Finish->MinDist[Column]=0;
  1999.     ThisDist[Column]=65535;
  2000.     }
  2001.   
  2002.   SearchCity=Finish;
  2003.   
  2004.   while (SearchCity)
  2005.     {
  2006.     for(Column=0; Column<2; Column++)
  2007.       {
  2008.       if(SearchCity->MinDist[Column] < Start->MinDist[Column])
  2009.         {
  2010.         //if(Column==0 && debugoutput)
  2011.         //  Printf("Scanning map at range: %ld: %s\n",
  2012.         //          SearchCity->MinDist[0],SearchCity->CityName);
  2013.         
  2014.         MiniVal=SearchCity->MinDist[Column];
  2015.         NextRoute=SearchCity->RoadList;
  2016.         NextCol=SearchCity->Colum;
  2017.         
  2018.         while (NextRoute)
  2019.           {
  2020.           ULONG dist;
  2021.           
  2022.           if(Column==0)
  2023.             { // We're talking distance
  2024.             dist=ConvertDist(NextRoute->Distance,NextRoute->Units,
  2025.               UNITS_METRIC);
  2026.             }
  2027.           else
  2028.             { // We're talking time
  2029.             dist=ConvertToTime(NextRoute->SpeedCode,NextRoute->Speed,
  2030.               NextRoute->Distance,NextRoute->Units,MeasureUnits);
  2031.             
  2032.             if(dist==0 && debugoutput)
  2033.               {
  2034.               Printf("Zero time: %s (%s - %s)\n",NextRoute->Hiway,
  2035.                 NextRoute->CityNum[0]->CityName,
  2036.                 NextRoute->CityNum[1]->CityName);
  2037.               }
  2038.             }
  2039.           
  2040.           OtherCity=NextRoute->CityNum[1-NextCol];
  2041.           Travel=MiniVal+dist;
  2042.           
  2043.           if (OtherCity->MinDist[Column] > Travel)
  2044.             /* found a new shortest path */
  2045.             {
  2046.             OtherCity->MinDist[Column]=Travel;
  2047.             OtherCity->NextCity[Column]=SearchCity;
  2048.             
  2049.             if(!OtherCity->WorkList && ELink!=OtherCity)
  2050.               {
  2051.               BLink=SearchCity;
  2052.               FLink=SearchCity->WorkList;
  2053.               
  2054.               while(FLink && Travel>FLink->MinDist[Column])
  2055.                 {
  2056.                 BLink=FLink;
  2057.                 FLink=BLink->WorkList;
  2058.                 }
  2059.               
  2060.               BLink->WorkList=OtherCity;
  2061.               OtherCity->WorkList=FLink;
  2062.               
  2063.               if (!FLink) ELink=OtherCity;
  2064.               }  /* build new Worklist */
  2065.             }    /* shorter total distance */
  2066.           
  2067.           if(Travel < ThisDist[Column]) ThisDist[Column]=Travel; 
  2068.           NewRoute=NextRoute->RLink[NextCol];
  2069.           NewCol=NextRoute->Colm[NextCol];
  2070.           NextRoute=NewRoute;
  2071.           NextCol=NewCol;
  2072.           }   /* Try another route from SearchCity */
  2073.         }     /* City within target range */
  2074.       }       /* Next Column */
  2075.     
  2076.     BLink=SearchCity->WorkList;
  2077.     SearchCity->WorkList=NULL;
  2078.     SearchCity=BLink;
  2079.     }  /* if SearchCity not zero, go back */
  2080.   
  2081.   for(Column=0; Column<2; Column++)
  2082.     {
  2083.     SearchCity=Start;
  2084.     FLink=SearchCity->NextCity[Column];
  2085.     while(FLink)
  2086.       {
  2087.       if(TrailPoint[Column]<MAXTRAIL)
  2088.     Trail[TrailPoint[Column]++][Column].ct_City=FLink;
  2089.       SearchCity=FLink;
  2090.       FLink=SearchCity->NextCity[Column];
  2091.       }  /* wend for next FLink */
  2092.     }    /* next Column */
  2093.   }
  2094.  
  2095. void PrintRoute(char *filename, struct CityData **point, UWORD points,
  2096.   BOOL isprinter)
  2097. {
  2098.   unsigned char Column, NextCol, NewCol, ColStart, ColEnd;
  2099.   unsigned short TrackTrail,Result[3][2],i;
  2100.   unsigned long mpg,truedist,truetime;
  2101.   struct CityData *FLink, *SearchCity;
  2102.   struct RouteData *NextRoute, *NewRoute;
  2103.   struct TripEntry te;
  2104.   BPTR file;
  2105.   static char tempstr[100];
  2106.   
  2107.   file=Open(filename,MODE_NEWFILE);
  2108.   if(!file)
  2109.     {
  2110.     if(isprinter)
  2111.       MUI_Request(app,NULL,0,NULL,"_Ok","Couldn't write to printer");
  2112.     else
  2113.       MUI_Request(app,NULL,0,NULL,"_Ok","Couldn't open output file\n%s",
  2114.         filename);
  2115.     return;
  2116.     }
  2117.   
  2118.   for(Column=0; Column<2; Column++)
  2119.     {
  2120.     Result[0][Column]=0;   /* dist */
  2121.     Result[1][Column]=0;   /* time */
  2122.     Result[2][Column]=0;   // fuel
  2123.     SearchCity=point[0];
  2124.     
  2125.     for(TrackTrail=0; TrackTrail<TrailPoint[Column]; TrackTrail++)
  2126.       {
  2127.       FLink=Trail[TrackTrail][Column].ct_City;
  2128.       NextRoute=SearchCity->RoadList;
  2129.       NextCol=SearchCity->Colum;
  2130.       
  2131.       while (NextRoute && FLink != NextRoute->CityNum[1-NextCol]) 
  2132.         {
  2133.         NewRoute=NextRoute->RLink[NextCol];
  2134.         NewCol=NextRoute->Colm[NextCol];
  2135.         NextRoute=NewRoute;
  2136.         NextCol=NewCol;
  2137.         }
  2138.       
  2139.       if(NextRoute->SpeedCode>=INTERSTATE_RURAL)
  2140.         mpg=MPG[NextRoute->SpeedCode-2];
  2141.       else
  2142.         mpg=DefaultMPG;
  2143.       
  2144.       truedist=ConvertDist(NextRoute->Distance,NextRoute->Units,MeasureUnits);
  2145.       truetime=ConvertToTime(NextRoute->SpeedCode,NextRoute->Speed,
  2146.         NextRoute->Distance,NextRoute->Units,MeasureUnits);
  2147.       
  2148.       Result[2][Column]=Result[2][Column]+((100*truedist/mpg)+50)/100;
  2149.       Result[1][Column]=Result[1][Column]+truetime;
  2150.       Result[0][Column]=Result[0][Column]+truedist;
  2151.       
  2152.       SearchCity=FLink;
  2153.       }  /* next Link */
  2154.     }    /* next Column */
  2155.   
  2156.   ColStart=0;
  2157.   ColEnd=1;
  2158.   
  2159.   if(Result[0][0]==Result[0][1])
  2160.     {
  2161.     ColStart=1;
  2162.     ColEnd=1;
  2163.     }
  2164.   
  2165.   if(Result[1][0]==Result[1][1])
  2166.     {
  2167.     ColStart=0;
  2168.     ColEnd=0;
  2169.     }
  2170.   
  2171.   for(Column=ColStart; Column<=ColEnd; Column++)
  2172.     {
  2173.     UWORD dist=0, time=0, cumdist=0, cumtime=0;
  2174.     
  2175.     FPrintf(file,"From:\t%s, %s\nTo:\t%s, %s\n",point[0]->CityName,
  2176.       point[0]->StateName,point[points-1]->CityName,
  2177.       point[points-1]->StateName);
  2178.     
  2179.     if(points>2)
  2180.       {
  2181.       FPrintf(file,"Via:\t");
  2182.       for(i=1;i<(points-1);i++)
  2183.         {
  2184.         FPrintf(file,"%s, %s\n",point[i]->CityName,point[i]->StateName);
  2185.         if(i<(points-2)) FPrintf(file,"\t");
  2186.                     else FPrintf(file,"\n");
  2187.         }
  2188.       }
  2189.     
  2190.     switch(Column)
  2191.       {
  2192.       case 0: FPrintf(file,"Shortest route\n");
  2193.               break;
  2194.       
  2195.       case 1: FPrintf(file,"Quickest route\n");
  2196.               break;
  2197.       
  2198.       case 2: FPrintf(file,"Preferred route\n");
  2199.               break;
  2200.       }
  2201.     
  2202.     SearchCity=point[0];
  2203.     for(TrackTrail=0; TrackTrail<TrailPoint[Column]; TrackTrail++)
  2204.       {
  2205.       FLink=Trail[TrackTrail][Column].ct_City;
  2206.       NextRoute=SearchCity->RoadList;
  2207.       NextCol=SearchCity->Colum;
  2208.       
  2209.       while (NextRoute && FLink!=NextRoute->CityNum[1-NextCol]) 
  2210.         {
  2211.         NewRoute=NextRoute->RLink[NextCol];
  2212.         NewCol=NextRoute->Colm[NextCol];
  2213.         NextRoute=NewRoute;
  2214.         NextCol=NewCol;
  2215.         }   /* wend, no NextRoute */
  2216.       /*  Print highway link information */
  2217.       
  2218.       te.te_Distance=ConvertDist(NextRoute->Distance,NextRoute->Units,
  2219.         MeasureUnits);
  2220.       te.te_Time=ConvertToTime(NextRoute->SpeedCode,NextRoute->Speed,
  2221.         NextRoute->Distance,NextRoute->Units,MeasureUnits);
  2222.       te.te_Route=NextRoute->Hiway;
  2223.       
  2224.       if(Stricmp(NextRoute->Exits[1-NextCol],""))
  2225.         {
  2226.         SPrintf(tempstr,"%s (Exit %s)",FLink->CityName,
  2227.           NextRoute->Exits[1-NextCol]);
  2228.         te.te_End=tempstr;
  2229.         }
  2230.       else te.te_End=FLink->CityName;
  2231.       
  2232.       dist+=te.te_Distance;
  2233.       time+=te.te_Time;
  2234.       
  2235.       cumdist+=te.te_Distance;
  2236.       cumtime+=te.te_Time;
  2237.       
  2238.       if(Stricmp(SearchCity->StateName,FLink->StateName))
  2239.         {
  2240.         FPrintf(file,"CROSSING FROM %s TO %s\n",SearchCity->StateName,
  2241.           FLink->StateName);
  2242.         }
  2243.       
  2244.       if(TrackTrail+1<TrailPoint[Column] && DisplayType &&
  2245.         !Trail[TrackTrail][Column].ct_Waypoint)
  2246.         {
  2247.         NextRoute=FLink->RoadList;
  2248.         NextCol=FLink->Colum;
  2249.         FLink=Trail[TrackTrail+1][Column].ct_City;
  2250.         
  2251.         while (NextRoute && FLink!=NextRoute->CityNum[1-NextCol]) 
  2252.           {
  2253.           NewRoute=NextRoute->RLink[NextCol];
  2254.           NewCol=NextRoute->Colm[NextCol];
  2255.           NextRoute=NewRoute;
  2256.           NextCol=NewCol;
  2257.           }   /* wend, no NextRoute */
  2258.         
  2259.         FLink=Trail[TrackTrail][Column].ct_City;
  2260.         
  2261.         if(DisplayType==DIS_ROUTECHANGE)
  2262.           {
  2263.           if(!Stricmp(NextRoute->Hiway,te.te_Route))
  2264.             {
  2265.             SearchCity=FLink;
  2266.             continue;
  2267.             }
  2268.           }
  2269.         
  2270.         if(DisplayType==DIS_STATECHANGE)
  2271.           {
  2272.           if(!Stricmp(FLink->StateName,SearchCity->StateName) &&
  2273.             !Stricmp(NextRoute->Hiway,te.te_Route))
  2274.             {
  2275.             SearchCity=FLink;
  2276.             continue;
  2277.             }
  2278.           }
  2279.         }
  2280.       
  2281.       FPrintf(file,"%4ld %s (%2ld:%02ld) [%4ld %s (%2ld:%02ld)] %s to %s\n",
  2282.         dist,distabbrevs[MeasureUnits],time/60,time%60,
  2283.         cumdist,distabbrevs[MeasureUnits],cumtime/60,cumtime%60,
  2284.         te.te_Route,te.te_End);
  2285.       
  2286.       if(Trail[TrackTrail][Column].ct_Waypoint)
  2287.         {
  2288.         FPrintf(file,"ARRIVED %s, %s: %ld %s%s - %ld:%02ld\n",
  2289.           FLink->CityName,FLink->StateName,
  2290.           cumdist,distnames[MeasureUnits],(cumdist==1 ? "" : "s"),
  2291.           cumtime/60,cumtime%60);
  2292.         
  2293.         cumdist=0;
  2294.         cumtime=0;
  2295.         }
  2296.       
  2297.       dist=0;
  2298.       time=0;
  2299.       
  2300.       SearchCity=FLink;
  2301.       }  /* next link */
  2302.     
  2303.     FPrintf(file,"\n");
  2304.     FPrintf(file,"     Total Distance: %ld %s%s\n",Result[0][Column],
  2305.       distnames[MeasureUnits],(Result[0][Column]==1 ? "" : "s"));
  2306.     FPrintf(file,"     Driving Time: %ld:%02ld\n",Result[1][Column]/60,
  2307.       Result[1][Column]%60);
  2308.     FPrintf(file,"     Fuel used: %ld %s%s\n",Result[2][Column],
  2309.       fuelunits[MeasureUnits],(Result[2][Column]==1 ? "" : "s"));
  2310.     
  2311.     if(isprinter) FPrintf(file,"\f");
  2312.              else FPrintf(file,"\n\n");
  2313.     }  /* next Column */
  2314.   
  2315.   Close(file);
  2316. }
  2317.